package cn.com.connext.scrm.service;

import cn.com.connext.scrm.domain.enumeration.BannerStatus;
import cn.com.connext.scrm.domain.master.BannerList;
import cn.com.connext.scrm.repository.master.BannerListRepository;
import cn.com.connext.scrm.service.dto.BannerListDTO;
import cn.com.connext.scrm.service.mapper.BannerListMapper;
import cn.com.connext.scrm.utils.RedisUtils;
import com.alibaba.fastjson.JSON;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by yuanyajun on 2018/7/23.
 */
@Service
@Transactional
public class BannerListService extends BaseService<BannerList, String> {

    private final Logger log = LoggerFactory.getLogger(BannerListService.class);

    private final BannerListRepository bannerListRepository;

    @Autowired
    private BannerListMapper bannerListMapper;

    @Autowired
    private RedisUtils redisUtils;

    private final static Object REDIS_LOCK = new Object();

    protected BannerListService(BannerListRepository bannerListRepository) {
        super(bannerListRepository);
        this.bannerListRepository = bannerListRepository;
    }

/*    public Specification<BannerList> getWhereClause(final BannerListDTO bannerListDTO) {
        Specification<BannerList> specification = (Root<BannerList> root, CriteriaQuery<?> query,
                                               CriteriaBuilder cb) -> {
            List<Predicate> predicates = new ArrayList<>();
            query.orderBy(cb.desc(root.get("orderNumber").as(ZonedDateTime.class)));
            Predicate[] ps = new Predicate[predicates.size()];
            return cb.and(predicates.toArray(ps));
        };
        return specification;
    }*/

    private Specification<BannerList> getWhereClause(final BannerListDTO bannerListDTO) {
        Specification<BannerList> specification = (Root<BannerList> root, CriteriaQuery<?> query,
                                                   CriteriaBuilder cb) -> {
            List<Predicate> predicates = new ArrayList<>();
    /*        Predicate lineFactoryLike = cb.notEqual(root.get("status"), OrderStatus.DELETED);
            predicates.add(lineFactoryLike);*/

            if (StringUtils.isNotEmpty(bannerListDTO.getName())) {
                Predicate lineFactoryLike_add = cb.like(root.get("name"), "%" + bannerListDTO.getName() + "%");
                predicates.add(lineFactoryLike_add);
            }
            if (StringUtils.isNotEmpty(bannerListDTO.getRedirectType())) {
                Predicate lineFactoryLike_add = cb.equal(root.get("redirectType"), bannerListDTO.getRedirectType());
                predicates.add(lineFactoryLike_add);
            }
            if (StringUtils.isNotEmpty(bannerListDTO.getRedirectH5Url())) {
                Predicate lineFactoryLike_add = cb.like(root.get("redirectH5Url"), "%" + bannerListDTO.getRedirectH5Url() + "%");
                predicates.add(lineFactoryLike_add);
            }
            if (StringUtils.isNotEmpty(bannerListDTO.getMiniProgranAppid())) {
                Predicate lineFactoryLike_add = cb.like(root.get("miniProgranAppid"), "%" + bannerListDTO.getMiniProgranAppid() + "%");
                predicates.add(lineFactoryLike_add);
            }
            if (StringUtils.isNotEmpty(bannerListDTO.getMiniProgranPath())) {
                Predicate lineFactoryLike_add = cb.like(root.get("miniProgranPath"), "%" + bannerListDTO.getMiniProgranPath() + "%");
                predicates.add(lineFactoryLike_add);
            }
            if (bannerListDTO.getStatus() != null) {
                Predicate lineFactoryLike_add = cb.equal(root.get("status"), bannerListDTO.getStatus());
                predicates.add(lineFactoryLike_add);
            }
            if (bannerListDTO.getType() != null) {
                Predicate lineFactoryLike_add = cb.equal(root.get("type"), bannerListDTO.getType());
                predicates.add(lineFactoryLike_add);
            }
            if (bannerListDTO.getDeleteFlag() != null) {
                Predicate lineFactoryLike_add = cb.equal(root.get("deleteFlag"), bannerListDTO.getDeleteFlag());
                predicates.add(lineFactoryLike_add);
            }
            query.orderBy(cb.asc(root.get("orderNumber")/*.as(ZonedDateTime.class)*/));
            Predicate[] ps = new Predicate[predicates.size()];
            return cb.and(predicates.toArray(ps));
        };
        return specification;
    }


    public Page<BannerListDTO> getAllBannerList(Pageable pageable, BannerListDTO bannerListDTO) {
        if (null == bannerListDTO) {
            bannerListDTO = new BannerListDTO();
        }
        Page<BannerList> result = bannerListRepository.findAll(getWhereClause(bannerListDTO), pageable);
        Page<BannerListDTO> page = result.map(item -> bannerListMapper.toDto(item));
        return page;
    }

    public BannerListDTO saveBannerList(BannerList bannerList) {
        log.debug("REST to save {} : {}", getEntityName(), bannerList);
        bannerList.setUpdateTime(ZonedDateTime.now());
        bannerList = bannerListRepository.save(bannerList);
        refreshCache();
        return bannerListMapper.toDto(bannerList);
    }

    public BannerListDTO findOneDTO(String id) {
        log.debug("Request to get BannerList : {}", id);
        BannerList bannerList = bannerListRepository.findOne(id);
        if (null != bannerList) {
            return bannerListMapper.toDto(bannerList);
        }
        return null;
    }

    public BannerListDTO updateBannerListById(BannerList bannerList) {
        log.debug("REST to update {} : {}", getEntityName(), bannerList);

        bannerList = bannerListRepository.save(bannerList);
        if (null != bannerList) {
            refreshCache();
            return bannerListMapper.toDto(bannerList);
        }
        return null;
    }

    public void deleteBanner(String id) {
        log.debug("Request to delete Circle : {}", id);
        BannerList bannerList = bannerListRepository.findOne(id);
        if (null != bannerList) {
            //bannerListRepository.delete(bannerList);

            bannerList.setDeleteFlag(true);
            bannerList.setUpdateTime(ZonedDateTime.now());
            bannerListRepository.save(bannerList);
            refreshCache();
        }
    }


    public void changeBannerStatus(String id) {
        log.debug("Request to delete Circle : {}", id);
        BannerList bannerList = bannerListRepository.findOne(id);
        if (null != bannerList) {
            Integer status = bannerList.getStatus();
            if (status.equals(BannerStatus.ENABLED.getCode())) {
                status = BannerStatus.DISABLED.getCode();
            }else{
                status = BannerStatus.ENABLED.getCode();
            }
            bannerList.setStatus(status);
            bannerList.setUpdateTime(ZonedDateTime.now());
            bannerListRepository.save(bannerList);
            refreshCache();
        }
    }

    public List<BannerListDTO> getBannerListByStatus(Integer type) {
        log.debug("Request to get BannerList : {}");
        long beginTime = System.currentTimeMillis();
        List<BannerListDTO> result = new ArrayList<>();
        List<BannerListDTO> dtoResult = new ArrayList<>();
        String redisKey = "banners-all";
        if (redisUtils.exists(redisKey)){
            result = (List<BannerListDTO>) redisUtils.get(redisKey);
            log.info("使用了缓存耗时："+(System.currentTimeMillis()-beginTime)+"ms");
        }else {
            BannerListDTO bannerListDTO = new BannerListDTO();
            bannerListDTO.setStatus(BannerStatus.ENABLED.getCode());
            bannerListDTO.setDeleteFlag(false);
            List<BannerList> list = bannerListRepository.findAll(getWhereClause(bannerListDTO));
            log.info("list:{}", list.size());
            List<BannerListDTO> dtoList = bannerListMapper.toDto(list);
            log.info("result:{}", dtoList.size());
            log.info("还未使用缓存耗时："+(System.currentTimeMillis()-beginTime)+"ms");
            redisUtils.set(redisKey, dtoList);
            result = dtoList;
        }
        if(type!=null){
            log.info("result:{}", result.size());
            for (BannerListDTO dto :result){
                if (dto.getType().equals(type)){
                    dtoResult.add(dto);
                }
            }
            return dtoResult;
        }
        return result;
    }


    public void refreshCache(){
//        List<Integer> typeList = bannerListRepository.findAllType();
//        for (Integer type : typeList){
            String redisKey = "banners-all";
            redisUtils.remove(redisKey);
            List<BannerList> result = null;
            BannerListDTO bannerListDTO = new BannerListDTO();
            bannerListDTO.setStatus(BannerStatus.ENABLED.getCode());
            bannerListDTO.setDeleteFlag(false);
            result = bannerListRepository.findAll(getWhereClause(bannerListDTO));
            List<BannerListDTO> dtoList = bannerListMapper.toDto(result);
            if (dtoList == null) {
                dtoList = new ArrayList<>();
            }
            redisUtils.set(redisKey, dtoList);
//        }
    }

    public void removeCache() {
        redisUtils.remove("banners-all");
    }
}
